import time

import shutil

import requests
from flask import request, abort, make_response
from flask_restful import Resource
from wechatpy import parse_message, create_reply, WeChatClient
from wechatpy.exceptions import InvalidSignatureException, InvalidAppIdException
from wechatpy.replies import ImageReply, EmptyReply
from wechatpy.utils import check_signature

from common.db import WechatUser

APPID = "wx785cc64305818927"
TOKEN = "GonFM02FzByiyVpQjbLh2tbWHVvHmlY3"
AES_KEY = "TUyJXoIx3sRcBNlhgidu2aTZKCQA7bpRNmkkHAs8oXB"
SECRET = "ddd0a9d0efdcbc22f35b065d6aab2dc4"


class Wechat(Resource):
    @staticmethod
    def get():
        signature = request.args.get('signature', '')
        timestamp = request.args.get('timestamp', '')
        nonce = request.args.get('nonce', '')
        try:
            check_signature(TOKEN, signature, timestamp, nonce)
        except InvalidSignatureException:
            abort(403)
        echo_str = request.args.get('echostr', '')
        return make_response(echo_str)

    @staticmethod
    def post():
        timestamp = request.args.get('timestamp', '')
        nonce = request.args.get('nonce', '')
        encrypt_type = request.args.get('encrypt_type', 'raw')
        msg_signature = request.args.get('msg_signature', '')
        if encrypt_type == 'raw':
            # plaintext mode
            msg = parse_message(request.data)
            if msg.type == 'text':
                reply = create_reply(msg.content, msg)
            elif msg.type == 'event':
                if msg.event == 'click':
                    if msg.key == 'MY_QRCODE':
                        from run import session
                        user = session.query(WechatUser).filter_by(username=msg.source).first()
                        reply = ImageReply()
                        reply.type = "image"
                        reply.media_id = user.qr_code_media_id
                        reply = create_reply(reply, msg)
                elif msg.event == 'subscribe_scan':
                    wechatUser = WechatUser()
                    wechatUser.username = msg.source
                    wechatUser.time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
                    from run import session
                    fromuser = session.query(WechatUser).filter_by(id=msg.scene_id).first()
                    if fromuser is not None and fromuser.username is not msg.source:
                        wechatUser.from_username = msg.scene_id
                    session.add(wechatUser)
                    session.commit()
                    create_qr_code(msg.source)
                    reply = create_reply("通过二维码关注", msg)
                elif msg.event == 'subscribe':
                    wechatUser = WechatUser()
                    wechatUser.username = msg.source
                    wechatUser.time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
                    from run import session
                    session.add(wechatUser)
                    session.commit()
                    create_qr_code(msg.source)
                    reply = create_reply("直接关注", msg)
                elif msg.event == 'unsubscribe':
                    from run import session
                    wechatUser = session.query(WechatUser).filter_by(username=msg.source).first()
                    session.delete(wechatUser)
                    session.commit()
                    reply = create_reply('Sorry, can not handle this for now', msg)
                elif msg.event == 'scan':
                    empty = EmptyReply()
                    reply = create_reply(empty, msg)
                else:
                    reply = create_reply('Sorry, can not handle this for now', msg)
            else:
                reply = create_reply('Sorry, can not handle this for now', msg)
            return make_response(reply.render())
        else:
            # encryption mode
            from wechatpy.crypto import WeChatCrypto

            crypto = WeChatCrypto(TOKEN, AES_KEY, APPID)
            try:
                msg = crypto.decrypt_message(
                    request.data,
                    msg_signature,
                    timestamp,
                    nonce
                )
            except (InvalidSignatureException, InvalidAppIdException):
                abort(403)
            else:
                msg = parse_message(msg)
                if msg.type == 'text':
                    reply = create_reply(msg.content, msg)
                else:
                    reply = create_reply('Sorry, can not handle this for now', msg)
                return crypto.encrypt_message(reply.render(), nonce, timestamp)


class WechatMenu(Resource):
    @staticmethod
    def get():
        client = WeChatClient(APPID, SECRET)
        client.menu.update({
            "button": [
                {
                    "type": "view",
                    "name": "解套",
                    "url": "https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=MzIwMzg5NDE3NQ==&scene=124#wechat_redirect"
                },
                {
                    "type": "view",
                    "name": "探底商城",
                    "url": "http://www.tandi.tech"
                },
                {
                    "type": "click",
                    "name": "我的二维码",
                    "key": "MY_QRCODE"
                }
            ]
        })


def create_qr_code(username):
    from run import session
    user = session.query(WechatUser).filter_by(username=username).first()
    client = WeChatClient(APPID, SECRET)
    res = client.qrcode.create({
        'expire_seconds': 2592000,
        'action_name': 'QR_SCENE',
        'action_info': {
            'scene': {'scene_id': user.id},
        }
    })
    url = client.qrcode.get_url(res.get('ticket'))
    r = requests.get(url, stream=True)
    filename = "qr_img/" + user.username + ".png"
    with open(filename, 'wb') as f:
        r.raw.decode_content = True
        shutil.copyfileobj(r.raw, f)
    f = open(filename, 'rb')
    res = client.media.upload("image", f)
    f.close()
    user.qr_code_media_id = res.get("media_id")
    user.qr_code_create_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
    session.add(user)
    session.commit()
